package com.simple.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import com.simple.exp.EndExcelException;
import com.simple.exp.EndSheetException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.xml.sax.InputSource;   
import org.xml.sax.SAXException;   
import org.xml.sax.XMLReader; 
  
public class ExcelUtil{
	
    private int sheetIndex = -1;   
    private String sheetName = "";
       
    private ExcelRowHandle excelRowHandle = null;
    
    /**  
     * 读取所有工作簿的入口方法  
     * @param path  
     * @throws Exception 
     */ 
    public void process(InputStream inputStream) throws Exception {
    	OPCPackage pkg = null;
    	pkg = OPCPackage.open(inputStream);
    	process(pkg);
    }
    
    /**  
     * 读取所有工作簿的入口方法  
     * @param path  
     * @throws Exception 
     */ 
    public void process(String path) throws Exception {
    	OPCPackage pkg = null;
    	pkg = OPCPackage.open(path);
    	process(pkg);
    }

    private void process(OPCPackage pkg) throws Exception {
    	try {
    		ReadOnlySharedStringsTable sst = new ReadOnlySharedStringsTable(pkg);
            XSSFReader xssfReader = new XSSFReader(pkg); 
            StylesTable styles = xssfReader.getStylesTable();
            XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
            while (iter.hasNext()) {  
                InputStream stream = iter.next();  
                sheetName = iter.getSheetName();  
                sheetIndex++;
                try{
                	processSheet(styles, sst, stream);  
                }
                catch(EndSheetException e){
                	if(excelRowHandle != null){
                		try {
                        	excelRowHandle.onSheetEnd(sheetIndex,sheetName);
                		}
                		catch (EndExcelException e1) {
                			break;
                		}
                    }
                	try{
                        stream.close();
                	}
                	catch(Exception e1){
                		
                	}
                	continue;
                }
                catch(EndExcelException e){
                	break;
                }
                catch(Exception e){
                	throw e;
                }
                finally {
                	try{
                        stream.close();
                	}
                	catch(Exception e){
                		
                	}
                }
                if(excelRowHandle != null){
                	try {
                    	excelRowHandle.onSheetEnd(sheetIndex,sheetName);
                	}
                	catch(EndExcelException e) {
                		break;
                	}
                }
            }
            excelRowHandle.onExcelEnd();
    	}
    	catch(Exception e) {
    		throw e;
    	}
    	finally {
    		if(pkg != null) {
    			pkg.close();
    		}
    	}
    }   
    
    public void processSheet(StylesTable styles, final ReadOnlySharedStringsTable sst, InputStream sheetInputStream)  
            throws IOException, ParserConfigurationException, SAXException, EndExcelException, EndSheetException {
        InputSource sheetSource = new InputSource(sheetInputStream);  
        SAXParserFactory saxFactory = SAXParserFactory.newInstance();  
        SAXParser saxParser = saxFactory.newSAXParser();  
        XMLReader sheetParser = saxParser.getXMLReader();
        sheetParser.setContentHandler(new SheetHandler(sst,styles,this));
        sheetParser.parse(sheetSource);
    }
       
    /**  
     * 该方法自动被调用，每读一行调用一次，在方法中写自己的业务逻辑即可 
     * @param sheetIndex 工作簿序号 
     * @param curRow 处理到第几行 
     * @param rowList 当前数据行的数据集合 
     */  
    protected void optRow(int curRow, List<String> rowList) {   
        if(excelRowHandle != null){
        	excelRowHandle.onRow(sheetIndex, sheetName, curRow, rowList);
        }
    }   
    
    public void setExcelRowHandle(ExcelRowHandle excelRowHandle){
    	this.excelRowHandle = excelRowHandle;
    }
    
    /**
     * 可以在任何onRow中抛出RuntimeException表示出错，导入会停止
     * @author lub
     */
    public interface ExcelRowHandle{
    	/**
    	 * 读取每一行的回调
    	 * @param sheetIndex
    	 * @param sheetName
    	 * @param curRow
    	 * @param rowList
    	 */
    	public void onRow(int sheetIndex, String sheetName, int curRow, List<String> rowList);
    	/**
    	 * 每一个sheet结束的回调（每个sheet结束  或者  主动throw new EndSheetException会调用， 主动调用throw new EndExcelException不会调用，这两个Exception表示正常流程，不是异常）
    	 * @param sheetIndex
    	 * @param sheetName
    	 */
    	public void onSheetEnd(int sheetIndex, String sheetName);
    	/**
    	 * 整个excel解析完成的回调（每个sheet结束  或者  主动throw new EndSheetException会调用， 这两个Exception表示正常流程，不是异常）
    	 */
    	public void onExcelEnd();
    }
}  
